#include "h_t_collect.h"

//delay us
static void HalIIC_Delayus(uint16_t count)
{
    uint8_t tempVal;

    while(count--)
    {
        tempVal = 5;
        while(tempVal--)
        {
            __NOP();
        }
    }
}

void HalSht20IIC_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = SHT20_IIC_SCL_PIN | SHT20_IIC_SDA_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(SHT20_IIC_PORT, &GPIO_InitStructure);

    sht20_iic_scl_h();
    sht20_iic_sda_h();
}

//??IIC????
static void HalSht20IIC_Start(void)
{
    sht20_i2c_sda_out();     //sda???
    sht20_iic_scl_h();
    sht20_iic_sda_h();
    HalIIC_Delayus(SHT20_IIC_DELAY_US);
    sht20_iic_sda_l(); //START:when CLK is high,DATA change form high to low
    HalIIC_Delayus(SHT20_IIC_DELAY_US);
    sht20_iic_scl_l(); //??I2C??,?????????
}
//??IIC????
static void HalSht20IIC_Stop(void)
{
    sht20_i2c_sda_out();//sda???
    sht20_iic_scl_l();
    sht20_iic_sda_l(); //STOP:when CLK is high DATA change form low to high
    HalIIC_Delayus(SHT20_IIC_DELAY_US);
    sht20_iic_scl_h();
    HalIIC_Delayus(SHT20_IIC_DELAY_US);
    sht20_iic_sda_h(); //??I2C??????
    HalIIC_Delayus(SHT20_IIC_DELAY_US);
}
//????????
//???:1,??????
//        0,??????
static uint8_t HalSht20IIC_Wait_Ack(void)
{
    uint32_t ucErrTime = 0;
    sht20_iic_sda_in();      //SDA?????
    HalIIC_Delayus(SHT20_IIC_DELAY_US);
    sht20_iic_scl_h();
    HalIIC_Delayus(SHT20_IIC_DELAY_US);
    while(sht20_iic_read_sda())
    {
        ucErrTime++;
        if(ucErrTime > SHT20_IIC_ACK_TIME_OUT)
        {
            //SysLog("Sht20_IIC_ACK_TIME_OUT");
            HalSht20IIC_Stop();
            return 1;
        }
    }

    sht20_iic_scl_l(); //????L
    return 0;
}
//??ACK??
static void HalSht20IIC_Ack(void)
{
    sht20_iic_scl_l();
    sht20_i2c_sda_out();
    sht20_iic_sda_l();
    HalIIC_Delayus(SHT20_IIC_DELAY_US);
    sht20_iic_scl_h();
    HalIIC_Delayus(SHT20_IIC_DELAY_US);
    sht20_iic_scl_l();
}

//???ACK??
static void HalSht20IIC_NAck(void)
{
    sht20_iic_scl_l();
    sht20_i2c_sda_out();
    sht20_iic_sda_h();
    HalIIC_Delayus(SHT20_IIC_DELAY_US);
    sht20_iic_scl_h();
    HalIIC_Delayus(SHT20_IIC_DELAY_US);
    sht20_iic_scl_l();
}
//IIC??????
//????????
//1,???
//0,???
static void HalSht20IIC_Send_Byte(uint8_t txd)
{
    uint8_t t;
    sht20_i2c_sda_out();
    sht20_iic_scl_l(); //??????????
    for(t = 0; t < 8; t++)
    {
        if(txd & 0x80)
        {
            sht20_iic_sda_h();
        }
        else
        {
            sht20_iic_sda_l();
        }
        txd <<= 1;
        HalIIC_Delayus(SHT20_IIC_DELAY_US);
        sht20_iic_scl_h();
        HalIIC_Delayus(SHT20_IIC_DELAY_US);
        sht20_iic_scl_l();
    }
    sht20_iic_sda_in();
}
//?1???,ack=1?,??ACK,ack=0,??nACK
static uint8_t HalSht20IIC_Read_Byte(uint8_t ack)
{
    uint8_t i, receive = 0;
    sht20_iic_sda_in();//SDA?????
    for(i = 0; i < 8; i++ )
    {
        sht20_iic_scl_l();
        HalIIC_Delayus(SHT20_IIC_DELAY_US);
        sht20_iic_scl_h();
        receive <<= 1;
        if(sht20_iic_read_sda())
        {
            receive++;
        }
        HalIIC_Delayus(SHT20_IIC_DELAY_US);
    }
    if (!ack)
    {
        HalSht20IIC_NAck();    //??nACK
    }
    else
    {
        HalSht20IIC_Ack();    //??ACK
    }
    return receive;
}

//?1???,ack=1?,??ACK,ack=0,??nACK
static uint8_t HalSht20IIC_Read_Byte2(uint8_t ack)
{
    uint8_t i, receive = 0;
    sht20_iic_sda_in();//SDA?????
    for(i = 0; i < 8; i++ )
    {
        sht20_iic_scl_h();
        HalIIC_Delayus(SHT20_IIC_DELAY_US);
        receive <<= 1;
        if(sht20_iic_read_sda())
        {
            receive++;
        }
        sht20_iic_scl_l();
        HalIIC_Delayus(SHT20_IIC_DELAY_US);
    }

    if (!ack)
    {
        HalSht20IIC_NAck();    //??nACK
    }
    else
    {
        HalSht20IIC_Ack();    //??ACK
    }
    return receive;
}

#define POLYNOMIAL 0x131 //P(x)=x^8+x^5+x^4+1 = 100110001

uint8_t HalSht20_CheckCrc (uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum)
{
    uint8_t crc = 0;
    uint8_t byteCtr;
    uint8_t bit;

    /* calculates 8-Bit checksum with given polynomial */
    for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
    {
        crc ^= (data[byteCtr]);
        for (bit = 8; bit > 0; --bit)
        {
            if (crc & 0x80)
            {
                crc = (crc << 1) ^ POLYNOMIAL;
            }
            else
            {
                crc = (crc << 1);
            }
        }
    }
    if (crc != checksum)
    {
        return 0xff;
    }
    else
    {
        return 0;
    }
}

/***********************************************************************************
** ???  :
** ????:
** ????:
** ????:
************************************************************************************/
uint8_t Hal_sht20_get_temperature(int32_t *k)
{
	#if 1
    uint8_t databuf[3];
    int32_t Temperature;

    HalSht20IIC_Start();

    HalSht20IIC_Send_Byte(0x80);
    HalSht20IIC_Wait_Ack();

    HalSht20IIC_Send_Byte(0xe3);
    HalSht20IIC_Wait_Ack();

    HalSht20IIC_Start();
    HalSht20IIC_Send_Byte(0x81);
    HalSht20IIC_Wait_Ack();

    sht20_iic_scl_in();

    while(0 == sht20_iic_read_scl())
    {
        __NOP();
    }

    sht20_iic_scl_h();
    sht20_i2c_scl_out();

    databuf[0] = HalSht20IIC_Read_Byte2(1);
    databuf[1] = HalSht20IIC_Read_Byte(1);
    databuf[2] = HalSht20IIC_Read_Byte(0);

    HalSht20IIC_Stop();

    if(HalSht20_CheckCrc(databuf, 2, databuf[2]))
    {
        os_log("Hal_sht20_get_temperature crc err!!!!!!!");
        return 0xff;
    }
    else
    {
        Temperature = (17572 * (databuf[0] << 8 | databuf[1]) >> 16) - 4685;
        os_log("Temperature:%d", Temperature/100);
        *k = 27315 + Temperature; /* ???????? */
        return 0;
    }
	#endif
}

/***********************************************************************************
** ???  :
** ????:
** ????:
** ????:
************************************************************************************/
uint8_t Hal_sht20_get_humidity(uint32_t *h)
{
#if 1	
    uint8_t databuf[3];
    uint32_t Humidity;

    HalSht20IIC_Start();

    HalSht20IIC_Send_Byte(0x80);
    HalSht20IIC_Wait_Ack();

    HalSht20IIC_Send_Byte(0xe5);
    HalSht20IIC_Wait_Ack();

    HalSht20IIC_Start();
    HalSht20IIC_Send_Byte(0x81);
    HalSht20IIC_Wait_Ack();

    sht20_iic_scl_in();

    while(0 == sht20_iic_read_scl())
    {
        __NOP();
    }

    sht20_iic_scl_h();
    sht20_i2c_scl_out();

    databuf[0] = HalSht20IIC_Read_Byte2(1);
    databuf[1] = HalSht20IIC_Read_Byte(1);
    databuf[2] = HalSht20IIC_Read_Byte(0);

    HalSht20IIC_Stop();

    if(HalSht20_CheckCrc(databuf, 2, databuf[2]))
    {
        os_log("Hal_sht20_get_humidity crc err!!!!!!!");
        return 0xff;
    }
    else
    {
        Humidity = (125 * (databuf[0] << 8 | databuf[1]) >> 16) - 6;
        os_log("Humidity:%d", Humidity);
        *h = Humidity; /* ?????? */
        return 0;
    }
#endif	
}

